/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.library.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springblade.common.enums.library.QuestionType;
import org.springblade.common.exception.TrainingServiceException;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.ObjectUtil;
import org.springblade.modules.library.bo.AutoExtractParamBO;
import org.springblade.modules.library.bo.AutoExtractQuestionBO;
import org.springblade.modules.library.excel.QuestionBankExcel;
import org.springblade.modules.library.excel.QuestionBankImporter;
import org.springblade.modules.library.entity.QuestionOptionEntity;
import org.springblade.modules.library.service.IQuestionOptionService;
import org.springblade.modules.library.vo.QuestionTypeNumVO;
import org.springblade.modules.material.entity.PaperDetailEntity;
import org.springblade.modules.material.service.IPaperDetailService;
import org.springblade.modules.material.service.IPaperService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.modules.library.entity.QuestionBankEntity;
import org.springblade.modules.library.vo.QuestionBankVO;
import org.springblade.modules.library.wrapper.QuestionBankWrapper;
import org.springblade.modules.library.service.IQuestionBankService;
import org.springblade.core.boot.ctrl.BladeController;
import org.springframework.web.multipart.MultipartFile;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 试题题库 控制器
 *
 * @author
 * @since 2023-03-22
 */
@RestController
@AllArgsConstructor
@RequestMapping("blade-questionBank/questionBank")
@Api(value = "试题题库", tags = "试题题库接口")
public class QuestionBankController extends BladeController {

	private final IQuestionBankService questionBankService;

	private final IQuestionOptionService questionOptionService;

	private final IPaperService paperService;
	private final IPaperDetailService paperDetailService;
	/**
	 * 试题题库 详情
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入questionBank")
	public R<QuestionBankVO> detail(QuestionBankEntity questionBank) {
		QuestionBankVO detail = questionBankService.selectQuestionDetails(questionBank);
		return R.data(detail);
	}

	/**
	 * 试题题库 分页
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入questionBank")
	public R<IPage<QuestionBankVO>> list(QuestionBankEntity questionBank, Query query) {

		LambdaQueryWrapper<QuestionBankEntity> queryWrapper=new LambdaQueryWrapper<>();
		if (null!=questionBank.getQuestionNumber()){
			queryWrapper.like(QuestionBankEntity::getQuestionNumber,questionBank.getQuestionNumber());
		}
		if (null!=questionBank.getQuestionType()){
			queryWrapper.eq(QuestionBankEntity::getQuestionType,questionBank.getQuestionType());
		}
		if (null!=questionBank.getQuestionProperties()){
			queryWrapper.like(QuestionBankEntity::getQuestionProperties,questionBank.getQuestionProperties());
		}
		if (null!=questionBank.getCategoryFirst()){
			queryWrapper.like(QuestionBankEntity::getCategoryFirst,questionBank.getCategoryFirst());
		}
		if (null!=questionBank.getCategorySecond()){
			queryWrapper.like(QuestionBankEntity::getCategoryFirst,questionBank.getCategorySecond());
		}
		if (null!=questionBank.getContent()){
			queryWrapper.like(QuestionBankEntity::getContent,questionBank.getContent());
		}
		if (null!=questionBank.getBankName()){
			queryWrapper.like(QuestionBankEntity::getBankName,questionBank.getBankName());
		}
		if (null!=questionBank.getAffiliationType()){
			queryWrapper.eq(QuestionBankEntity::getAffiliationType,questionBank.getAffiliationType());
		}
//		IPage<QuestionBankEntity> pages = questionBankService.page(Condition.getPage(query), Condition.getQueryWrapper(questionBank)
//			.lambda().like(QuestionBankEntity::getQuestionNumber,questionNumber));
		IPage<QuestionBankEntity> pages = questionBankService.page(Condition.getPage(query),queryWrapper );
		return R.data(QuestionBankWrapper.build().pageVO(pages));
	}

	/**
	 * 试题题库 自定义分页
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/page")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "自定义分页(手动组卷题目范围))", notes = "传入questionBank")
	public R<IPage<QuestionBankEntity>> page(QuestionBankVO questionBank, Query query) {
		IPage<QuestionBankEntity> pages = questionBankService.selectQuestionBankPage(Condition.getPage(query), questionBank);
		return R.data(pages);
	}

	/**
	 * 试题题库 新增
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入questionBank")
	public R save(@Valid @RequestBody QuestionBankEntity questionBank) {
		return R.status(questionBankService.save(questionBank));
	}


	/**
	 * 试题题库 修改
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入questionBank")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public R update(@Valid  @RequestBody List<QuestionBankVO> questionBankVOList ) {
		questionBankVOList.stream().forEach(questionBankVO->{
			QuestionBankEntity questionBank = new QuestionBankEntity();
			BeanUtil.copyProperties(questionBankVO, questionBank);
			if (ObjectUtils.isEmpty(questionBank)) {
				throw new ServiceException("参数错误");
			}

			try { questionBankVO.setContent(URLDecoder.decode(questionBankVO.getContent(),"UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
			try { questionBankVO.setProblemAnalysis(URLDecoder.decode(questionBankVO.getProblemAnalysis(),"UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
			questionBank.setChapterId(questionBankVO.getChapterId());
			questionBank.setSubId(questionBankVO.getSubId());
			questionBankService.updateById(questionBank);
			//修改选项
			if (CollectionUtils.isNotEmpty(questionBankVO.getOptionVOList())) {
				questionOptionService.remove(Wrappers.<QuestionOptionEntity>query().lambda().eq(QuestionOptionEntity::getQuestionBankId,questionBank.getId()));
				questionBankVO.getOptionVOList().forEach(questionOptionEntity -> {
					questionOptionEntity.setId(null);
					try { questionOptionEntity.setOption(URLDecoder.decode(questionOptionEntity.getOption(),"UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
					questionOptionService.save(questionOptionEntity);
				});

			}
		});
		return R.success("修改成功");
	}


	/**
	 * 试题题库 删除
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		questionOptionService.remove( Wrappers.<QuestionOptionEntity>query().lambda().in(QuestionOptionEntity::getQuestionBankId, Func.toLongList(ids))  );
		return R.status(questionBankService.deleteLogic(Func.toLongList(ids)));
	}

	/**
	 * 试题题库 批量新增
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/save-batch")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "批量新增", notes = "传入questionBankList")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public R< List<QuestionBankVO> > saveBatch(@Valid @RequestBody List<QuestionBankVO> questionBankVOList) {
		List<QuestionBankVO> resultData=new ArrayList<>();

		questionBankVOList.forEach(questionBankVO -> {
			try { questionBankVO.setContent(URLDecoder.decode(questionBankVO.getContent(),"UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
			try { questionBankVO.setProblemAnalysis(URLDecoder.decode(questionBankVO.getProblemAnalysis(),"UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
			questionBankService.save(questionBankVO);
			questionBankVO.setQuestionId(questionBankVO.getId());//返回给前端的

			if (questionBankVO.getQuestionType()==QuestionType.SHORT.getCode().intValue()
				&&CollectionUtil.isEmpty(questionBankVO.getOptionVOList())  ){ //如果是简答题 并且没有设置选项或者选项大于1个,则默认新增一个选项

				QuestionOptionEntity questionOptionEntityShort=new QuestionOptionEntity();
				questionOptionEntityShort.setIsRight(1);
				questionOptionEntityShort.setQuestionBankId(questionBankVO.getId());
				questionOptionService.save(questionOptionEntityShort);
				questionBankVO.setOptionVOList(Collections.singletonList(questionOptionEntityShort));
			}else {
				//optionVOList转化为List<QuestionOptionEntity>
				List<QuestionOptionEntity> optionEntityList =  questionBankVO.getOptionVOList().stream().map(optionVO -> {
					QuestionOptionEntity optionEntity = new QuestionOptionEntity();
					BeanUtil.copy(optionVO, optionEntity);
					//base64解析选项内容
					try { optionEntity.setOption(URLDecoder.decode(optionEntity.getOption(),"UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
					optionEntity.setQuestionBankId(questionBankVO.getId());
					return optionEntity;
				}).collect(Collectors.toList());
				questionOptionService.saveBatch(optionEntityList);
				questionBankVO.setOptionVOList(optionEntityList);
				questionBankVO.setQuestionId(questionBankVO.getId());
			}

			resultData.add(questionBankVO);
		});
		return R.data(resultData);
	}

	/**
	 * 手工录入试题
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/manual-save-question")
	@ApiOperationSupport(order = 9)
	@ApiOperation(value = "手工录入试题", notes = "传入questionBankList")
	public R manualSaveQuestion(@Valid @RequestBody List<QuestionBankEntity> questionBankList) {
		questionBankList.forEach(questionBankService::save);
		return R.data(questionBankList);
	}

	/**
	 * 自动组卷抽取试题
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/auto-extract-question")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "自动组卷抽取试题", notes = "传入bo")
	public R autoExtractQuestion(@RequestBody @Valid AutoExtractQuestionBO bo) {
		List<AutoExtractParamBO> paramList = bo.getParamsList();
		ArrayList<QuestionBankVO> totalList = new ArrayList<>();
		List<Long> selectedQuestionIds=new ArrayList<>();
		paramList.forEach(item -> {
			if (null==item.getExtractQuality()) throw new TrainingServiceException("请填写抽取数量");
			//查出满足条件的数据，题目类型 ，难度，抽取位置
			item.setAffiliationType(null);
			item.setSelectedQuestionIds(selectedQuestionIds);
			List<QuestionBankVO> queryList = questionBankService.selectQuestionBankByParams(item);
			if (CollectionUtil.isEmpty(queryList))return;
			selectedQuestionIds.addAll(queryList.stream().map(QuestionBankVO::getId).collect(Collectors.toList()));
			queryList.forEach(queryVo->{ //附上选项
				queryVo.setOptionVOList(questionOptionService.list(Wrappers.<QuestionOptionEntity>query()
					.lambda().eq(QuestionOptionEntity::getQuestionBankId,queryVo.getId())));
			});
			//打乱subList
//			Collections.shuffle(queryList);
//			通过Stream流取subList的前x条记录
//			Integer quantity = 1;
//			if (ObjectUtils.isNotEmpty(item.getExtractQuality())) {
//				quantity = item.getExtractQuality();
//			}
//			totalList.addAll(queryList.stream().limit(quantity).collect(Collectors.toList()));
			totalList.addAll(queryList);
		});

		//根据题型分组
		Map<Integer, List<QuestionBankVO>> collectMap =totalList.stream().collect(Collectors.groupingBy(QuestionBankVO::getQuestionType));

		List<QuestionBankVO> sortList=new ArrayList<>();
		for(QuestionType questionType:QuestionType.values()){
			//获取对应题目类型的数据
			List<QuestionBankVO> questionTypeList = collectMap.get(questionType.getCode());
			if (CollectionUtil.isNotEmpty(questionTypeList)) sortList.addAll(questionTypeList);
		}
		return R.data(sortList);
	}


	/**
	 * 题库名称下拉列表
	 */
	@GetMapping("/bankName-select")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "题库名称下拉列表", notes = "可传入题库名称")
	public R bankNameSelect(String bankName) {
		LambdaQueryWrapper<QuestionBankEntity> lambdaQueryWrapper=new LambdaQueryWrapper<>();
		if (StringUtils.isNotBlank(bankName)) lambdaQueryWrapper.like(QuestionBankEntity::getBankName,bankName);
		List<QuestionBankEntity> list = questionBankService.list(lambdaQueryWrapper);
		List<String> bankNames=new ArrayList<>();
		if (CollectionUtil.isNotEmpty(list)){
			 bankNames = list.stream().map(QuestionBankEntity::getBankName).distinct().collect(Collectors.toList());
		}
		return R.data(bankNames);
	}



	/**
	 * 根据题目名称，获得题目性质下拉列表
	 */
	@GetMapping("/questionProperties-select")
	@ApiOperationSupport(order = 12)
	@ApiOperation(value = "题目性质下拉列表", notes = "根据题库名称，获得题目性质下拉列表")
	public R questionPropertiesSelect(String bankName,String questionProperties) {
		LambdaQueryWrapper<QuestionBankEntity> lambdaQueryWrapper=new LambdaQueryWrapper<>();
		if (StringUtils.isNotBlank(bankName)) lambdaQueryWrapper.eq(QuestionBankEntity::getBankName,bankName);
		if (StringUtils.isNotBlank(questionProperties)) lambdaQueryWrapper.eq(QuestionBankEntity::getQuestionProperties,questionProperties);
		List<QuestionBankEntity> list = questionBankService.list(lambdaQueryWrapper);
		List<String> questionPropertiesName=new ArrayList<>();
		if (CollectionUtil.isNotEmpty(list)){
			questionPropertiesName = list.stream().map(QuestionBankEntity::getQuestionProperties).distinct().collect(Collectors.toList());
		}
		return R.data(questionPropertiesName);
	}


	/**
	 * 根据题库名称、题目性质 得出各类型题的题目数量
	 */
	@GetMapping("/questionType-num")
	@ApiOperationSupport(order = 13)
	@ApiOperation(value = "根据题库名称、题目性质 得出各类型题的题目数量", notes = "题库名称、题目性质")
	public R getQuestionTypeByBankNameAndQuestionProperties(QuestionBankEntity questionBankEntity) {
		QuestionTypeNumVO result=new QuestionTypeNumVO();
		List<QuestionTypeNumVO> list = questionBankService.getQuestionTypeByBankNameAndQuestionProperties(questionBankEntity);
		list.forEach(vo->{
			Integer num = vo.getNum();
			if (null==num || num<0) num=0;
			if (vo.getDifficultyLevel()==1){
				if (vo.getQuestionType()==1)result.setPrimarySingle(num);
				if (vo.getQuestionType()==2)result.setPrimaryMultiple(num);
				if (vo.getQuestionType()==3)result.setPrimaryJudge(num);
				if (vo.getQuestionType()==5)result.setPrimaryShort(num);
			}

			if (vo.getDifficultyLevel()==2){
				if (vo.getQuestionType()==1)result.setIntermediateSingle(num);
				if (vo.getQuestionType()==2)result.setIntermediateMultiple(num);
				if (vo.getQuestionType()==3)result.setIntermediateJudge(num);
				if (vo.getQuestionType()==5)result.setIntermediateShort(num);
			}

			if (vo.getDifficultyLevel()==3){
				if (vo.getQuestionType()==1)result.setSeniorSingle(num);
				if (vo.getQuestionType()==2)result.setSeniorMultiple(num);
				if (vo.getQuestionType()==3)result.setSeniorJudge(num);
				if (vo.getQuestionType()==5)result.setSeniorShort(num);
			}
		});

		return R.data(result);
	}


	/**
	 * 根据题库名称、题目性质 检测每道题目是否完整
	 */
	@GetMapping("/detection-questionType-complete")
	@ApiOperationSupport(order = 13)
	@ApiOperation(value = " 根据题库名称、题目性质 检测每道题目是否完整", notes = "题库名称、题目性质,检查规则detectionTyppe=1、检查试卷detectionTyppe=2 且要传paperId")
	public R questionCompleteFlag(QuestionBankVO questionBankEntity) {
		List<QuestionBankEntity> errorList=new ArrayList<>();//错误的题目
		List<QuestionBankEntity> list=new ArrayList<>();
		if (null!=questionBankEntity.getDetectionType() && questionBankEntity.getDetectionType()==1){//检查规则的题
			list = questionBankService.list(Wrappers.<QuestionBankEntity>query().lambda()
				.eq(QuestionBankEntity::getQuestionProperties,questionBankEntity.getQuestionProperties())
				.eq(QuestionBankEntity::getBankName,questionBankEntity.getBankName()));
		}

		if (null!=questionBankEntity.getDetectionType() && questionBankEntity.getDetectionType()==2){//检查试卷的题
			List<PaperDetailEntity> paperDetailEntityList = paperDetailService.list(Wrappers.<PaperDetailEntity>query().lambda().eq(PaperDetailEntity::getPid, questionBankEntity.getPaperId()));

			if (CollectionUtil.isNotEmpty(paperDetailEntityList)){
				list=paperDetailEntityList.stream().map(vo-> questionBankService.getById(vo.getQuestionBankId())).collect(Collectors.toList());
			 }

		}

		if (CollectionUtil.isNotEmpty(list)) {
			list.forEach(vo -> {
				try {
					if (null==vo ||null==vo.getId()|| null==vo.getQuestionType() )return;
					boolean completeFlag = questionBankService.questionCompleteFlag(vo.getId(), vo.getQuestionType());
					if (!completeFlag) errorList.add(vo);
				}catch (Exception e){
					System.out.println(e.getMessage());
				}

			});
		}
		boolean flag=true;
		Map<String,Object> result=new HashMap<>();
		if (CollectionUtil.isEmpty(errorList))flag=false;
		result.put("flag",flag);
		result.put("errorList",errorList);
		return R.data(result);
	}




	/**
	 * 批量导入试题
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("import-bank")
	@ApiOperationSupport(order = 20)
	@ApiOperation(value = "批量导入试题", notes = "传入excel")
	public R importQuestionBank(MultipartFile file) {
		QuestionBankImporter questionBankImporter = new QuestionBankImporter(questionBankService,questionOptionService);
		ExcelUtil.save(file, questionBankImporter, QuestionBankExcel.class);
		return R.success("操作成功");
	}

	/**
	 * 导出模板
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("export-bank-template")
	@ApiOperationSupport(order = 21)
	@ApiOperation(value = "导出模板")
	public void exportUser(HttpServletResponse response) {
		List<QuestionBankExcel> list = new ArrayList<>();
		ExcelUtil.export(response, "试题数据模板", "试题数据表", list, QuestionBankExcel.class);
	}

}
